package com.android.equipment.utils;

import android.os.Build;

import androidx.annotation.RequiresApi;

import com.blankj.utilcode.util.ArrayUtils;
import com.blankj.utilcode.util.StringUtils;

import java.math.BigDecimal;
import java.nio.ByteBuffer;
import java.nio.charset.Charset;
import java.time.LocalDateTime;
import java.util.Arrays;

/**
 * 进制转换工具类
 * 用的进制转换算法请统一封装到这个类里面
 */
//@Slf4j
public class BinaryParseUtil {

    //private static final log log = logFactory.getlog(BinaryParseUtil.class);

    /**
     * 将int值转为指定长度的byte[], 值为0或1,即二进制位值
     * 索引从小到大 --> bit从低到高
     *
     * @param data
     * @param len
     * @return
     */
    public static byte[] parseBinByteArray(Integer data, int len) {
        byte[] ret = new byte[len];
        for (int i = 0; i < len; i++) {
            ret[i] = (byte) ((data >> i) % 2);
        }
        return ret;
    }
    //将16进制字符串转为byte数组
    public static byte[] hexStringToByteArray(String hexString) {
        // 去除字符串前后的空格
        hexString = hexString.trim();

        // 确保字符串的长度是偶数
        if (hexString.length() % 2 != 0) {
            throw new IllegalArgumentException("Invalid hex string");
        }

        // 计算字节数组的长度
        int byteArrayLength = hexString.length() / 2;
        byte[] byteArray = new byte[byteArrayLength];

        // 逐个解析两个字符，将其转换为字节
        for (int i = 0; i < byteArrayLength; i++) {
            int firstDigit = Character.digit(hexString.charAt(i * 2), 16);
            int secondDigit = Character.digit(hexString.charAt(i * 2 + 1), 16);

            if (firstDigit == -1 || secondDigit == -1) {
                throw new IllegalArgumentException("Invalid hex string");
            }

            byteArray[i] = (byte) ((firstDigit << 4) + secondDigit);
        }

        return byteArray;
    }
    //将一个byte值转为8位长度的二进制数组
    public static byte[] parseBinByteArray(byte val, int len) {
        byte ret[] = new byte[len];
        for (int i = 0; i < len; i++) {
            ret[i] = (byte) (((val & 0xFF) >> i) % 2);
        }
        return ret;
    }

    /**
     * 将int值转为一个指定长度的int[]
     * 索引从小到大 --> bit从低到高
     *
     * @param data
     * @param len
     * @return
     */
    public static int[] parseBinaryArray(int data, int len) {
        int[] ret = new int[len];
        for (int i = 0; i < len; i++) {
            ret[i] = ((data >> i) % 2);
        }
        return ret;
    }

    /**
     * 将一个俩字节长的数组转为一个指定长度的长度的二进制数组
     * 默认为小端模式, 低字节在前,高字节在后
     * !!! 不是小端模式的不要用这个方法
     *
     * @param data
     * @param len
     * @return
     */
    public static int[] parseIntArraySmallModel(byte[] data, int len) {
        int intFromBytes = getIntFromBytes(data[1], data[0]);
        return parseBinaryArray(intFromBytes, len);
    }

    /**
     * 将16进制字符串转换为byte[]
     *
     * @param str
     * @return
     */
    public static byte[] toBytes(String str) {
        str = str.replaceAll(" ", "");
        if (str == null || str.trim().equals("")) {
            return new byte[0];
        }

        byte[] bytes = new byte[str.length() / 2];
        for (int i = 0; i < str.length() / 2; i++) {
            String subStr = str.substring(i * 2, i * 2 + 2);
            bytes[i] = (byte) Integer.parseInt(subStr, 16);
        }

        return bytes;
    }

    public static short[] toShorts(String hex) {
        if (hex != null) {
            hex = hex.replaceAll(" ", "");
            short[] shorts = new short[hex.length() / 4];
            for (int i = 0; i < hex.length() / 4; i++) {
                String subStr = hex.substring(i * 4, i * 4 + 4);
                shorts[i] = (short) Integer.parseInt(subStr, 16);
            }
            return shorts;
        }
        return new short[0];
    }

    /**
     * 将一个byte数组转为16进制字符串
     *
     * @param bytes
     * @return
     */
    public static String parseHexStr(byte[] bytes) {
        StringBuilder sb = new StringBuilder();
        for (byte aByte : bytes) {
            int val = aByte & 0xff;
            sb.append(String.format("%02x", val & 0xff));
        }
        return sb.toString().toUpperCase();
    }

    /**
     * 将一个short数组转为hex字符串
     * @param shorts short数组
     * @return hexStr
     */
    public static String parseHexStr(short[] shorts) {
        StringBuilder sb = new StringBuilder();
        for (short aShort : shorts) {
            int val = aShort & 0xffff;
            sb.append(String.format("%04x", val));
        }
        return sb.toString().toUpperCase();
    }
    /**
     * 字节转16进制字符串
     *
     * @param bytes
     * @return
     */
    public static String bytesToHexFun3(byte[] bytes,int model) {
        byte[] array = new byte[bytes.length];
        //如果是小端模式,需要进行高低位互换
        if (model == 0) {
            for (int i = 0; i < array.length; i++) {
                array[i] = bytes[bytes.length - (i + 1)];
            }
        } else {
            array = bytes;
        }
        StringBuilder buf = new StringBuilder(array.length * 2);
        for (byte b : array) { // 使用String的format方法进行转换
            buf.append(String.format("%02x", b & 0xff));
        }
        return buf.toString().toUpperCase();
    }

    /**
     * 字节转16进制字符串
     *
     * @param bytes
     * @return
     */
    public static String bytesToHexFun3(byte[] bytes) {
        StringBuilder buf = new StringBuilder(bytes.length * 2);
        for (byte b : bytes) { // 使用String的format方法进行转换
            buf.append(String.format("%02x", b & 0xff));
        }
        return buf.toString().toUpperCase();
    }

    /**
     * @param srcData 原数组
     * @param start   数组开始下标
     * @param end     数组截止下标
     * @return 一个新的截取数组
     */
    public static byte[] getSubData(byte[] srcData, int start, int end) {
        return Arrays.copyOfRange(srcData, start, end);
    }

    public static int[] getSubData(int[] srcData, int start, int end) {
        return Arrays.copyOfRange(srcData, start, end);
    }

    /**
     * 把一个字节数组转为int, 传参之前确定高低字节
     *
     * @param high_h 高字节 高位
     * @param high_l 高字节 低位
     * @param low_h  低字节 高位
     * @param low_l  低字节 低位
     * @return
     */
    public static int getIntFromBytes(byte high_h, byte high_l, byte low_h, byte low_l) {
        return (high_h & 0xff) << 24 | (high_l & 0xff) << 16 | (low_h & 0xff) << 8 | low_l & 0xff;
    }

    /**
     * 把一个两字节长的转为一个int
     *
     * @param high
     * @param low
     * @return
     */
    public static int getIntFromBytes(byte high, byte low) {
        return (high & 0xff) << 8 | low & 0xff;
    }

    /**
     * 把一个十进制字节数组转为一个int值
     *
     * @param bytes 需要转换的数组
     * @param model 大小端模式, 传入数据的模式, 大端: 高字节在前;  小端:低字节在前
     * @return
     */
    public static int getIntFromBytes(byte[] bytes, int model) {
        if (bytes == null || bytes.length == 0) {
            //log.error("传入的字节数组为空");
            return 0;
        }
        byte[] array = new byte[bytes.length];
        //如果是大端模式,需要进行高低位互换, ==>高字节在索引大的位置,这样位运算的时候 可以直接左移它的索引*8位
        if (model == 1) {
            for (int i = 0; i < array.length; i++) {
                array[i] = bytes[bytes.length - (i + 1)];
            }
        } else {
            array = bytes;
        }
        int sum = 0;
        for (int i = 0; i < array.length; i++) {
            sum = sum | (array[i] & 0xFF) << (8 * i);
        }
        return sum;
    }

    /**
     * 把一个二进制数组转为一个int值
     *
     * @param bytes 二进制数组
     * @param model 如果传入数组的0索引是最低bit,就符合大段模式, model必须传1, 否则就传0
     *              大小端模式  传入数据的模式
     *              1:大端, 即:bytes按索引增的顺序与10进制值的二进制位权从大到小是一直的,高位在前,低位在后
     *              比如: byte 为 : {0, 1, 0, 1}
     *              int值为5,其二进制从高bit到低bit: 0101
     *              0:小端
     *              byte为: {1,0,1,0}  其索引0位是二进制的最低bit
     * @return
     */
    public static int getIntFromBinary(int[] bytes, int model) {
        if (bytes == null || bytes.length == 0) {
            //log.error("传入的字节数组为空");
            return 0;
        }
        int[] array = new int[bytes.length];
        //如果是大端模式,需要进行高低位互换, ==>高字节在索引大的位置,这样位运算的时候 可以直接左移它的索引*8位
        if (model == 1) {
            for (int i = 0; i < array.length; i++) {
                array[i] = bytes[bytes.length - (i + 1)];
            }
        } else {
            array = bytes;
        }
        int sum = 0;
        for (int i = 0; i < array.length; i++) {
            sum += (array[i] << i);
        }
        return sum;
    }


    /**
     * 针对设备数据为float类型
     *
     * @param bytes         10进制字节数组
     * @param model         大小端模式: 0小端,低位在前, 1大端,高位在前
     * @param decimalPlaces 保留小数位数
     * @return double
     */
    public static double bytesToDouble(byte[] bytes, int model, int decimalPlaces) {
        if (bytes == null || bytes.length == 0) {
            //log.error("传入的字节数组为空");
            return 0;
        }
        byte[] array = new byte[bytes.length];
        //如果是小端模式,需要进行高低位互换
        if (model == 0) {
            for (int i = 0; i < array.length; i++) {
                array[i] = bytes[bytes.length - (i + 1)];
            }
        } else {
            array = bytes;
        }
        int sum = 0;
        for (int i = 0; i < array.length; i++) {
            sum = sum | (array[i] & 0xFF) << (8 * (array.length - 1 - i));
        }
        float v = Float.intBitsToFloat(sum);
        System.out.println("--------------" + v);
        BigDecimal b = new BigDecimal(v);
        return b.setScale(decimalPlaces, BigDecimal.ROUND_HALF_UP).doubleValue();
    }

    /**
     * 针对设备数据为float类型
     *
     * @param bytes         10进制字节数组
     * @param model         大小端模式: 0小端,低位在前, 1大端,高位在前
     * @param decimalPlaces 保留小数位数
     * @return double
     */
    public static float bytesToFloat(byte[] bytes, int model, int decimalPlaces) {
        if (bytes == null || bytes.length == 0) {
            //log.error("传入的字节数组为空");
            return 0;
        }
        byte[] array = new byte[bytes.length];
        //如果是小端模式,需要进行高低位互换
        if (model == 0) {
            for (int i = 0; i < array.length; i++) {
                array[i] = bytes[bytes.length - (i + 1)];
            }
        } else {
            array = bytes;
        }
        int sum = 0;
        for (int i = 0; i < array.length; i++) {
            sum = sum | (array[i] & 0xFF) << (8 * (array.length - 1 - i));
        }
        float v = Float.intBitsToFloat(sum);
        System.out.println("--------------" + v);
        BigDecimal b = new BigDecimal(v);
        return b.setScale(decimalPlaces, BigDecimal.ROUND_HALF_UP).floatValue();
    }


    /**
     * 与上一个方法结果一致
     *
     * @param bytes         字节数组
     * @param model         大小端模式: 0小端,低位在前, 1大端,高位在前
     * @param decimalPlaces 保留小数位数
     * @return double
     */
    public static double bytesToDouble2(byte[] bytes, int model, int decimalPlaces) {
        if (bytes == null || bytes.length == 0) {
            //log.error("传入的字节数组为空");
            return 0;
        }
        byte[] array = new byte[bytes.length];
        //如果是大端模式,将高低位互换, 方便下面或运算时的字节位移
        if (model == 1) {
            for (int i = 0; i < array.length; i++) {
                array[i] = bytes[bytes.length - (i + 1)];
            }
        } else {
            array = bytes;
        }
        int sum = 0;
        for (int i = 0; i < array.length; i++) {
            sum = sum | (array[i] & 0xFF) << (8 * i);
        }
        float v = Float.intBitsToFloat(sum);
//        System.out.println("--------------" + v);
        BigDecimal b = new BigDecimal(v);
        return b.setScale(decimalPlaces, BigDecimal.ROUND_HALF_UP).doubleValue();
    }
//    public static float bytesToFloat(byte[] bytes) {
//        ByteBuffer buffer = ByteBuffer.allocate(4);
//        buffer.put(bytes);
//        buffer.flip();
//        return buffer.getFloat();
//    }

    /**
     *
     * byte[] array = new byte[bytes.length];
     *         //如果是小端模式,需要进行高低位互换
     *         if (model == 0) {
     *             for (int i = 0; i < array.length; i++) {
     *                 array[i] = bytes[bytes.length - (i + 1)];
     *             }
     *         } else {
     *             array = bytes;
     *         }
     * @param bytes
     * @return
     */
    public static long bytesToUInt32(byte[] bytes,int model) {
        byte[] array = new byte[bytes.length];
        //如果是小端模式,需要进行高低位互换
        if (model == 0) {
            for (int i = 0; i < array.length; i++) {
                array[i] = bytes[bytes.length - (i + 1)];
            }
        } else {
            array = bytes;
        }
        ByteBuffer buffer = ByteBuffer.allocate(4);
        buffer.put(array);
        buffer.flip(); // 需要在读取前翻转
        return buffer.getInt() & 0xFFFFFFFFL; // 转换为正数
    }
    public static long bytesToUInt16(byte[] bytes,int model) {
        byte[] array = new byte[bytes.length];
        //如果是小端模式,需要进行高低位互换
        if (model == 0) {
            for (int i = 0; i < array.length; i++) {
                array[i] = bytes[bytes.length - (i + 1)];
            }
        } else {
            array = bytes;
        }
        ByteBuffer buffer = ByteBuffer.allocate(2);
        buffer.put(array);
        buffer.flip(); // 需要在读取前翻转
        return buffer.getInt() & 0xFFFFFFFFL; // 转换为正数
    }
    /**
     * @param bytes
     * @param model
     * @param decimalPlaces
     * @return
     */
    public static double bytesToDouble3(byte[] bytes, int model, int decimalPlaces) {
        if (bytes == null || bytes.length == 0) {
            //log.error("传入的字节数组为空");
            return 0;
        }
        byte[] array = new byte[bytes.length];
        //如果是大端模式,将高低位互换, 方便下面或运算时的字节位移
        if (model == 1) {
            for (int i = 0; i < array.length; i++) {
                array[i] = bytes[bytes.length - (i + 1)];
            }
        } else {
            array = bytes;
        }
        int sum = 0;
        for (int i = 0; i < array.length; i++) {
            sum = sum | (array[i] & 0xFF) << (8 * i);
        }
        return sum / (decimalPlaces * 10D);
        //return b.setScale(decimalPlaces, BigDecimal.ROUND_HALF_UP).doubleValue();
    }


    /**
     * 根据模拟量设置信息和模拟量字节获取模拟量实际值
     * 适用于信息体类型为3的数据解析
     *
     * @param dateSetInfo 模拟量设置信息
     * @param dataVal     模拟量值字节
     * @return double类型的实际值
     */
    public static double getSimuVal(byte dateSetInfo, byte[] dataVal) {
        byte[] binaryIntArr = parseBinByteArray(dateSetInfo, 8);
        double val = (dataVal[1] & 0xFF) * 256 + (dataVal[0] & 0xFF);
        //小数点移动位数
        int pointMoveNum = Integer.valueOf(binaryIntArr[2] + "" + binaryIntArr[1] + "" + binaryIntArr[0], 2);

        int multipNum = 1;
        for (int i = 0; i < pointMoveNum; i++) {
            multipNum *= 10;
        }

        //0表示小数点往前移
        //1表示小数点往后移
        int rule = binaryIntArr[3];
        if (rule == 0) {
            val = val / multipNum;
        } else {
            val = val * multipNum;
        }
        //1表示数据为负
        //0表示数据为正
        int inLessThanZero = binaryIntArr[7];
        if (inLessThanZero == 1) {
            return val * -1;
        }
        return val;
    }

    public static Double getSimuVal(byte dateSetInfo, Double val) {
        byte[] binaryIntArr = parseBinByteArray(dateSetInfo, 8);
        //小数点移动位数
        int pointMoveNum = Integer.valueOf(binaryIntArr[2] + "" + binaryIntArr[1] + "" + binaryIntArr[0], 2);

        int multipNum = 1;
        for (int i = 0; i < pointMoveNum; i++) {
            multipNum *= 10;
        }

        //0表示小数点往前移
        //1表示小数点往后移
        int rule = binaryIntArr[3];
        if (rule == 0) {
            val = val / multipNum;
        } else {

            val = val * multipNum;
        }
        //1表示数据为负
        //0表示数据为正
        int inLessThanZero = binaryIntArr[7];
        if (inLessThanZero == 1) {
            return val * -1;
        }
        return val;
    }
    public static byte[] byteByModel(byte[] bytes,int model){
        byte[] array = new byte[bytes.length];
        if (bytes == null || bytes.length == 0) {
            //log.error("传入的字节数组为空");
            return array;
        }
        //如果是大端模式,将高低位互换, 方便下面或运算时的字节位移
        if (model == 1) {
            for (int i = 0; i < array.length; i++) {
                array[i] = bytes[bytes.length - (i + 1)];
            }
        } else {
            array = bytes;
        }
        return array;
    }
    public static byte[] byteMergerAll(byte[]... values) {
        int length_byte = 0;
        for (int i = 0; i < values.length; i++) {
            length_byte += values[i].length;
        }
        byte[] all_byte = new byte[length_byte];
        int countLength = 0;
        for (int i = 0; i < values.length; i++) {
            byte[] b = values[i];
            System.arraycopy(b, 0, all_byte, countLength, b.length);
            countLength += b.length;
        }
        return all_byte;
    }

    /**
     * 把ascii码转为字符串
     *
     * @param devSig ascii
     * @return 字符串
     */
    public static String asciiToStr(byte[] devSig) {
        if (devSig != null && devSig.length > 0) {
            StringBuilder sb = new StringBuilder();
            for (int i = 0; i < devSig.length; i++) {
                sb.append((char) devSig[i]);
            }
            return sb.toString().trim();
        }
        return null;
    }

    /**
     * 将一个byte值转为一个8位的二进制数组,低位0 高位7
     *
     * @param val byte
     * @return byte[]
     */
    public static byte[] byteToByteArr(byte val) {
        byte[] arr = new byte[8];
        for (int i = 0; i < arr.length; i++) {
            arr[i] = (byte) (((val & 0xFF) >> i) % 2);
        }
        return arr;
    }

    /**
     * 校验和
     *
     * @param msg    需要计算校验和的byte数组
     * @param length 校验和位数
     * @return 计算出的校验和数组  索引0是低字节
     */
    public static byte[] sumCheck(byte[] msg, int length) {
        long mSum = 0;
        byte[] mByte = new byte[length];

        /** 逐Byte添加位数和 */
        for (byte byteMsg : msg) {
            long mNum = ((long) byteMsg >= 0) ? (long) byteMsg : ((long) byteMsg + 256);
            mSum += mNum;
        } /** end of for (byte byteMsg : msg) */

        /** 位数和转化为Byte数组 */
        for (int liv_Count = 0; liv_Count < length; liv_Count++) {
            mByte[length - liv_Count - 1] = (byte) (mSum >> (liv_Count * 8) & 0xff);
        } /** end of for (int liv_Count = 0; liv_Count < length; liv_Count++) */

        return mByte;
    }

    /**
     * CRC16校验算法
     *
     * @param data
     * @return
     */
    public static String getCRC16_ModbusCheckValue(String data) {
        int crc = 0XFFFF;
        byte[] bytes = toBytes(data);
        for (int i = 0; i < bytes.length; i++) {
            // 2. 把第一个8位二进制数据（即通讯信息帧的第一个字节）与16位的CRC寄存器的相异或，异或的结果仍存放于该CRC寄存器中
            crc ^= (bytes[i] & 0xFF);
//            crc ^= bytes[i];
            for (int j = 0; j < 8; j++) {
                // 3. 把CRC寄存器的内容右移一位，用0填补最高位，并检测移出位是0还是1
                if ((crc & 0x1) == 1) {
                    // 4. 如果移出位为1，CRC寄存器与0XA001进行异或
                    crc = (crc >> 1) ^ 0XA001;
                } else {
                    // 4.如果移出位为零，则重复第三步
                    crc >>= 1;
                }
                // 5. 重复步骤3和4，直到右移8次，这样整个8位数据全部进行了处理
            }
            // 6. 重复步骤2和5，进行通讯信息帧下一个字节的处理
        }
//        System.out.println(String.format("%4x", crc));
        // 7. 将该通讯信息帧所有字节按上述步骤计算完成后，得到的16位CRC寄存器的高、低字节进行交换
        int y = crc >> 8 | (crc & 0x00FF) << 8;

//        System.out.println(String.format("%04x", y));
        // 8. 最后得到的CRC寄存器内容即为：CRC校验码
        // todo 不够4位的时候需要前导0
        return String.format("%04x", y).toUpperCase();
    }

    public static String getCRC16_ModbusCheckValue(byte[] bytes) {
        int crc = 0XFFFF;
        //byte[] bytes = BytesHexStrTranslate.toBytes(data);
        for (int i = 0; i < bytes.length; i++) {
            // 2. 把第一个8位二进制数据（即通讯信息帧的第一个字节）与16位的CRC寄存器的相异或，异或的结果仍存放于该CRC寄存器中
            crc ^= (bytes[i] & 0xFF);
//            crc ^= bytes[i];
            for (int j = 0; j < 8; j++) {
                // 3. 把CRC寄存器的内容右移一位，用0填补最高位，并检测移出位是0还是1
                if ((crc & 0x1) == 1) {
                    // 4. 如果移出位为1，CRC寄存器与0XA001进行异或
                    crc = (crc >> 1) ^ 0XA001;
                } else {
                    // 4.如果移出位为零，则重复第三步
                    crc >>= 1;
                }
                // 5. 重复步骤3和4，直到右移8次，这样整个8位数据全部进行了处理
            }
            // 6. 重复步骤2和5，进行通讯信息帧下一个字节的处理
        }
//        System.out.println(String.format("%4x", crc));
        // 7. 将该通讯信息帧所有字节按上述步骤计算完成后，得到的16位CRC寄存器的高、低字节进行交换
        int y = crc >> 8 | (crc & 0x00FF) << 8;
//        System.out.println(String.format("%4x", y));
        // 8. 最后得到的CRC寄存器内容即为：CRC校验码
        return String.format("%4x", y).toUpperCase();
    }




    //======================================================数值转byte[]=======================================================================

    /**
     * 把一个int转为两字节长度的数组
     *
     * @param val    数值
     * @param model  大小端模式, 0小端, 1大端  返回数据的模式
     * @param length 指定长度  -- 只能返回两个长度的数组   呵呵:)
     * @return
     */
    public static byte[] intToDoubleBytes(int val, int model, int length) {
        if (length <= 0) {
            return new byte[0];
        }
        byte[] arr = new byte[2];
        //低字节的索引大, 高字节的索引小 ---符合大端模式
        arr[0] = (byte) ((val & 0xFF00) >> 8);
        arr[1] = (byte) (val & 0xFF);
        if (model == 0) {
            //反转一下数组
            ArrayUtils.reverse(arr);
        }
        return arr;
    }


    /**
     * 把一个byte数组转为int数组
     * @param bytes
     * @return
     */
    public static int[] byteArrToIntArr(byte[] bytes){
        int[] ints = new int[bytes.length];
        for (int i = 0; i < ints.length; i++) {
            ints[i] = bytes[i];
        }
        return ints;
    }


    /**
     * 获取校验和
     *
     * @param toCheckBytes
     * @return
     */
    public static int getCheckSum(byte[] toCheckBytes) {
        int sum = 0;
        for (byte aByte : toCheckBytes) {
            sum += (aByte & 0xFF);
        }
        return sum;
    }
    public static int getCheckSum(byte[] toCheckBytes,int model) {
        int sum = 0;
        for (byte aByte : toCheckBytes) {
            sum += (model==1)?Math.abs(aByte & 0xFF):(aByte & 0xFF);
        }
        return sum;
    }

    /**
     * 获取当前时间的字节数组
     * 年是两位制的
     * 索引从低到高是秒 分 时 日 月 年(两位)
     */
    @RequiresApi(api = Build.VERSION_CODES.O)
    public static byte[] getNowTimeBytes() {
        LocalDateTime now = LocalDateTime.now();
        String year = ("" + now.getYear()).substring(2);
        int monthValue = now.getMonthValue();
        int dayOfMonth = now.getDayOfMonth();
        int hour = now.getHour();
        int minute = now.getMinute();
        int second = now.getSecond();
        byte[] time = new byte[6];
        time[0] = (byte) second;
        time[1] = (byte) minute;
        time[2] = (byte) hour;
        time[3] = (byte) dayOfMonth;
        time[4] = (byte) monthValue;
        time[5] = (byte) Integer.parseInt(year);
        return time;
    }

    /**
     * 清除掉指定字符串后面的00
     * 默认包头为两个字节
     *
     * @param sig     指定标识
     * @param udpData 原始UDP数据hex字符串
     * @return 清洗后的字符串
     */
    public static String clear00AfterSig(String sig, String udpData) {
        if (StringUtils.isTrimEmpty(sig)) {
            throw new RuntimeException("指定标识字符串不能为空");
        }
        sig = sig.toUpperCase();
        udpData = udpData.toUpperCase();
        int length = udpData.length();
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < length / 2; i++) {
            try {
                String hexBy = udpData.substring(i * 2, i * 2 + 2);
                if (i >= 2 && sig.equals(hexBy)) {
                    String isZero = udpData.substring(i * 2 + 2, i * 2 + 4);
                    if ("00".equals(isZero)) {
                        i++;
                    }
                }
                sb.append(hexBy);
            } catch (Exception e) {
                System.out.println(sig + "=======" + udpData);//FFFF145100009D3C5103004027740C17E50543A9FF
                e.printStackTrace();
            }
        }
        return sb.toString();
    }

    public static String clear00AfterSigUpdateCD(String sig, String udpData) {
        if (StringUtils.isTrimEmpty(sig)) {
            throw new RuntimeException("指定标识字符串不能为空");
        }
        sig = sig.toUpperCase();
        udpData = udpData.toUpperCase();
        int length = udpData.length();
        StringBuilder sb = new StringBuilder();
        int num = 0;
        for (int i = 0; i < length / 2; i++) {
            try {
                String hexBy = udpData.substring(i * 2, i * 2 + 2);
                if (i >= 2 && sig.equals(hexBy)) {
                    String isZero = udpData.substring(i * 2 + 2, i * 2 + 4);
                    if ("00".equals(isZero)) {
                        i++;
                        num++;
                    }
                }
                sb.append(hexBy);
            } catch (Exception e) {
                System.out.println(sig + "=======" + udpData);//FFFF145100009D3C5103004027740C17E50543A9FF
                e.printStackTrace();
            }
        }
        String str = sb.toString();
        if (num > 0) {
            Integer changdu = Integer.parseInt(str.substring(4, 6), 16);
            changdu = changdu - num;
            sb.replace(4, 6, Integer.toHexString(changdu));
            str = sb.toString();
        }
        return str;
    }


    /**
     * 向指定标识后面加00
     * <p>
     * 用于处理 除了包头和包长外的字节FF/其他 时后加00
     *
     * @param hexStr 不包含包头和包长
     * @return
     */
    public static String insert00AfterSig(String sig, String hexStr) {
        if (StringUtils.isTrimEmpty(sig)) {
            throw new RuntimeException("指定标识字符串不能为空");
        }
        sig = sig.toUpperCase();
        StringBuilder sb = new StringBuilder();
        int length = hexStr.length();
        for (int i = 0; i < length / 2; i++) {
            String substring = hexStr.substring(i * 2, i * 2 + 2);
            if (sig.equalsIgnoreCase(substring)) {
                substring += "00";
            }
            sb.append(substring);
        }
        return sb.toString().toUpperCase();
    }

    /**
     * 向指定标识后面加00
     *
     * @param sig    指定标识, 一般未包头字节
     * @param allHex 完整的hex
     * @param skip   跳过的字节数, 2代表跳过前两个字节, 从其后的字符串,遇上sig 后加00
     * @return
     */
    public static String insert00AfterSig(String sig, String allHex, int skip) {
        if (StringUtils.isTrimEmpty(sig)) {
            throw new RuntimeException("指定标识字符串不能为空");
        }
        sig = sig.toUpperCase();
        StringBuilder sb = new StringBuilder();
        int length = allHex.length();
        for (int i = 0; i < length / 2; i++) {
            String substring = allHex.substring(i * 2, i * 2 + 2);
            if (i >= skip && sig.equalsIgnoreCase(substring)) {
                substring += "00";
            }
            sb.append(substring);
        }
        return sb.toString();
    }

    /**
     * 向指定标识后面加00
     *
     * @param sig    指定标识, 一般未包头字节
     * @param allHex 完整的hex
     * @param skip   跳过的字节数, 2代表跳过前两个字节, 从其后的字符串,遇上sig 后加00
     * @return
     */
    public static String insert00AfterSigUpdateCD(String sig, String allHex, int skip) {
        if (StringUtils.isTrimEmpty(sig)) {
            throw new RuntimeException("指定标识字符串不能为空");
        }
        sig = sig.toUpperCase();
        StringBuilder sb = new StringBuilder();
        int num = 0;
        int length = allHex.length();
        for (int i = 0; i < length / 2; i++) {
            String substring = allHex.substring(i * 2, i * 2 + 2);
            if (i >= skip && sig.equalsIgnoreCase(substring)) {
                substring += "00";
                num++;
            }
            sb.append(substring);
        }
        String str = sb.toString();
        if (num > 0) {
            Integer changdu = Integer.parseInt(str.substring(4, 6), 16);
            changdu = changdu + num;
            sb.replace(4, 6, Integer.toHexString(changdu));
            str = sb.toString();
        }
        return str;
    }

    /**
     * hex字符串转为ascii字符串
     *
     * @param string 普通原始字符串
     * @return ascii 的16进制字符串
     */
    public static String stringToUpcaseAsciiHex(String string) {
        if (StringUtils.isTrimEmpty(string)) {
            return "";
        }
        StringBuilder sb = new StringBuilder();
        char[] chars = string.toCharArray();
        for (char aChar : chars) {
            sb.append(Integer.toHexString(aChar));
        }
        return sb.toString().toUpperCase();
    }

    //    /**
//     * 升级校验和
//     */
    public static Integer upgradeCheck(byte[] data1) {
        int check_jieshou_sum = 0;    //接收数据时计算的校验和
        //最后一个字节为0x00，上一个字节为0xFF,则校验和为倒数第二个字节 如若不是则为倒数第一个字节
        int check_sum = data1[2] - 1;
        int receive_sum = data1[check_sum];
        for (int i = 3; i < check_sum; i++) {
            check_jieshou_sum += (data1[i] & 0xff);
        }
        //将0xFF后为00的数据剔除
        if ((receive_sum & 0xff) == (check_jieshou_sum & 0xff)) {
            return 0;
        }
        return 1;
    }

    /**
     * 两个字节的byte转short
     *
     * @param hight
     * @param low
     * @return
     */
    public static short bytesToShort(byte hight, byte low) {
        return (short) ((hight & 0xFF) << 8 | (low & 0xFF));
    }

    /**
     * 二进制位数组转为short,
     * ints数组得索引值对应bit位索引值----索引0 对 bit0
     * 每一位都要左移它对应的索引值 位数
     *
     * @param ints 0/1标志位
     * @return short
     */
    public static short binaryArrayToShort(int[] ints) {
        if (ints == null || ints.length == 0) {
            return 0;
        }
        int leng = Math.min(ints.length, 16);
        int val = 0;
        for (int i = 0; i < leng; i++) {
            val = val | (ints[i] << i);
        }
        return (short) (val & 0xFFFF);
    }


    /**
     * NB模组RSRP按比例转换为CSQ范围信号
     *
     * @param RSRP NB模组的信号强度指示为RSRP， 范围[-140, -44]；
     * @return GPRS模组信号强度指示CSQ， 范围[0, 31]；
     */
    public static int rsrpToCSQ(int RSRP) {
        int csq = 0;
        //限制RSRP范围
        if (RSRP > -44 || RSRP < -140){
            return 0;
        }

        RSRP = -RSRP;

        //映射为25~31信号 5格信号 满信号
        if (RSRP <= 70) {
            csq = 25 + (70 - RSRP) / 3;
            if (csq > 31) csq = 31;
        }
        //映射为20~24信号 4格信号
        else if (RSRP <= 80) {
            csq = 20 + (80 - RSRP) / 2;
        }
        //映射为15~19信号 3格信号
        else if (RSRP <= 90) {
            csq = 15 + (90 - RSRP) / 2;
        }
        //映射为10~14信号 2格信号
        else if (RSRP <= 100) {
            csq = 10 + (100 - RSRP) / 2;
        }
        //映射为5~9信号   1格信号
        else if (RSRP <= 105) {
            csq = 5 + (105 - RSRP);
        }
        //无信号 RSRP小于 -115, 模组无法工作
        //其余信号值固定显示为3
        else {
            csq = RSRP > 115 ? 0 : 3;
        }
        return csq;
    }


    /**
     * 解码, 将byte数字转为GB18030字符串
     * @param bytes
     */
    public static String deocdeToTextGB18030(byte[] bytes) {
       return new String(bytes, Charset.forName("GB18030"));
    }


    /**
     * 解析小端时间字节,
     *
     * @param timeBytes 时间字节数组
     * @return 时间
     */
    @RequiresApi(api = Build.VERSION_CODES.O)
    public static LocalDateTime decodeTimeBytes(byte[] timeBytes) {
//        if (timeBytes.length != 6) {
//            throw new ServiceException("时间字节长度不等于6");
//        }
        int year = 2000 + (timeBytes[5] & 0xFF);
        int month = timeBytes[4] & 0xFF;
        int day = timeBytes[3] & 0xFF;
        int hour = timeBytes[2] & 0xFF;
        int minute = timeBytes[1] & 0xFF;
        int second = timeBytes[0] & 0xFF;

        return LocalDateTime.of(year, month, day, hour, minute, second);
    }
}
